`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    21:11:47 01/17/2013 
// Design Name: 
// Module Name:    decode 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
`include "define.v"
module decode(
			  input  clk,
              input  rst_n,
			  input  [7:0] f_opcode,
			  input [2:0] f_stat,
			  input [3:0]  f_rA,
			  input [3:0]  f_rB,
			  input [3:0]  f_rC,
			  input [15:0]  f_valImm,
			  input   m_cnd,
			  
	          output  [7:0] d_opcode,
			  output reg[2:0] d_stat,
			  output [31:0] d_valImm,
			  output reg[31:0] d_valA,
			  output reg[31:0] d_valB,
			  output reg[3:0] d_dstE,
			  output reg[3:0] d_dstM,
		      output reg    [3:0] d_srcA,
		      output reg    [3:0] d_srcB,   
              
		      input [3:0] e_dstE,
		      input [31:0] e_valE,
              input [31:0]  m_valE,
              input  [3:0] m_dstE, 
		      input [31:0]   m_valM,
			  input  [3:0] m_dstM,
			  input [31:0]  w_valE,
			  input  [3:0] w_dstE,
			  input [31:0]  w_valM,
			  input  [3:0] w_dstM,
              input [1:0] w_wordselE,
              input [1:0] w_wordselM,
			  input   D_stall,
			  input   D_bubble
    );
wire   [3:0] d_rA,d_rB,d_rC;
wire   [31:0] d_rvalA,d_rvalB;

always @(d_opcode or d_rA)
begin
    casez(d_opcode)
	{`NORM_INS,`RMMOV16},
    {`NORM_INS,`RMMOV32},
    {`NORM_INS,`MRMOV16},
    {`NORM_INS,`MRMOV32},
    {`NORM_INS,`RRMOV16},
    {`NORM_INS,`RRMOV32},
    {`NORM_INS,`GROUP_OP,4'b????},
	{`NORM_INS,`PUSH}:d_srcA<=d_rA;
	
	{`NORM_INS,`POP},
	{`NORM_INS,`RET}:d_srcA<=`RSP;
	default:d_srcA<= `RNULL;
    endcase
end
always @ (d_opcode or d_rB)
begin
    casez(d_opcode)
    {`NORM_INS,`RMMOV16},
    {`NORM_INS,`RMMOV32},
	{`NORM_INS,`GROUP_OP,4'b????}:d_srcB<=d_rB;
	
	{`NORM_INS,`POP},
	{`NORM_INS,`RET},
    {`NORM_INS,`CALL},
	{`NORM_INS,`PUSH}:d_srcB<=`RSP;
	default:d_srcB<=`RNULL;
    endcase
end
always @(d_opcode or d_rB or d_rC)
begin
    case(d_opcode)
	{`NORM_INS,`RRMOV16},
    {`NORM_INS,`RRMOV32},    
    {`NORM_INS,`IRMOV16} :d_dstE<=d_rB;
	{`NORM_INS,`GROUP_OP,4'b????}:d_dstE<=d_rC;

    {`NORM_INS,`POP},
	{`NORM_INS,`RET},
    {`NORM_INS,`CALL},
	{`NORM_INS,`PUSH}:d_dstE<=`RSP;
	default:d_dstE<= `RNULL;
    endcase
end

always @(d_opcode or d_rB)
begin
    case(d_opcode)	
    {`NORM_INS,`MRMOV16},
    {`NORM_INS,`MRMOV32},
    {`NORM_INS,`POP}     :d_dstM<=d_rB;
    
	default:d_dstM<= `RNULL;
    endcase
end

//sel+fwd A
always @ (d_srcA or d_opcode or e_valE or e_dstE or m_dstM or m_dstE or m_valE or m_valM or w_dstE or w_dstM or w_valM or w_valE or d_rvalA)
begin
    if(d_opcode=={`NORM_INS,`CALL} || d_opcode[7:4]=={`NORM_INS,`GROUP_JMP})
	d_valA<=d_valImm;
    else if(d_srcA==e_dstE)
	d_valA<=e_valE;
    else if(d_srcA==m_dstM)
	d_valA<=m_valM;
    else if(d_srcA==m_dstE)
	d_valA<=m_valE;
    else if(d_srcA==w_dstM)
	d_valA<=w_valM;
    else if(d_srcA==w_dstE)
	d_valA<=w_valE;
    else
	d_valA<=d_rvalA;	
end
//fwd B
always @ (d_srcB or e_dstE or e_valE
or m_dstM or m_valM
or m_dstE or m_valE 
or w_dstM or w_valM
or w_dstE or w_valE
or d_rvalB)
begin
    if(d_srcB==e_dstE)
	d_valB<=e_valE;
    else if(d_srcB==m_dstM)
	d_valB<=m_valM;
    else if(d_srcB==m_dstE)
	d_valB<=m_valE;
    else if(d_srcB==w_dstM)
	d_valB<=w_valM;
    else if(d_srcB==w_dstE)
	d_valB<=w_valE;
    else
	d_valB<=d_rvalB;
end
always @ (posedge clk or negedge rst_n)
begin
	if(~rst_n)
	    d_stat<=`ST_AOK;
	else
	begin
	    if(D_stall)
            d_stat<=d_stat;
	    else if(D_bubble)
            d_stat<=`ST_AOK;
	    else
            d_stat<=f_stat;
	end
end
ppregs_D U_ppregs_D
    (
	.clk(clk),
	.rst_n(rst_n),
	.D_stall(D_stall),
    .D_bubble(D_bubble),
	.opcode_i(f_opcode),
	.rA_i(f_rA),
	.rB_i(f_rB),
    .rC_i(f_rC),
	.valImm_i(f_valImm),
	
	.opcode_o(d_opcode),
	.rA_o(d_rA),
	.rB_o(d_rB),
    .rC_o(d_rC),
	.valImm_o(d_valImm)
    );
	 
regFile U_regFile(
    //outputs
    .d_rvalA(d_rvalA),//[31:0]
    .d_rvalB(d_rvalB),//[31:0]
    //inputs
    .clk(clk),
    .rst_n(rst_n),
    .d_srcA(d_srcA),//[3:0]
    .d_srcB(d_srcB),//[3:0]
    .w_dstE(w_dstE),//[3:0]
    .w_dstM(w_dstM),//[3:0]
    .w_valE(w_valE),//[31:0]
    .w_valM(w_valM),//[31:0]
    .w_wordselE(w_wordselE),//00-rx,01-rxL,1x-rxH
    .w_wordselM(w_wordselM)//00-rx,01-rxL,1x-rxH
    );

endmodule
